package com.ibatis4J.framework.dal.dao.support.sql;

import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

import com.ibatis4J.framework.dal.exception.DalException;

import freemarker.template.Configuration;
import freemarker.template.Template;

/**
 * FreeMaker解析，实现SQL渲染
 * 
 * @author liuwenya
 *
 */
public class FreeMakerParser {
	
	/**默认模板KEY*/
	private static final String DEFAULT_TEMPLATE_KEY="default_template_key";
	
	/**配置器*/
	private static final Configuration CONFIGURER=new Configuration();
	
	/**配置SQL表达式缓存*/
	private static Map<String, Template> templateCache=new HashMap<String, Template>();
	
	/**配置SQL生成器表达式缓存*/
	private static Map<String, Template> expressionCache = new HashMap<String, Template>();
	
	/**
	 * 静态代码块
	 */
	static{
		CONFIGURER.setClassicCompatible(true);
	}
	
	/**
	 * 构造方法
	 */
	private FreeMakerParser(){
		
	}
	
	public static String process(String expression, Map<String, Object> root){
		StringReader reader = null;
		StringWriter out = null;
		Template template = null;

		try {
			if (expressionCache.get(expression) != null) {
				template = expressionCache.get(expression);
			}
			if (template == null) {
				template = createTemplate(DEFAULT_TEMPLATE_KEY, new StringReader(expression));
				expressionCache.put(expression, template);
			}
			out = new StringWriter();
			template.process(root, out);
			return out.toString();
		} catch (Exception e) {
			throw new DalException("error.dal.005", e );
		}finally {
			if(reader != null){
				reader.close();
			}
			try {
				if(out != null){
					out.close();
				}
			} catch (Exception e2) {
			}
		}

		
	}
	
	
	/**
	 * 创建模板
	 * 
	 * @param templateKey  模板键值
	 * @param reader       待处理字符流
	 * @return     模板
	 * @throws IOException  IO异常
	 */
	private static Template createTemplate(String templateKey,StringReader reader) throws IOException{
		Template template=new Template(templateKey, reader,CONFIGURER);
		template.setNumberFormat("#");
		return template;
	}
	/**
	 * 动态解析处理方法
	 * 
	 * @param root root对象
	 * @param sql  SQL串
	 * @param sqlId  SQLID
	 * @return      StringWrite字符串
	 */
	public static String process(Map<String,Object> root,String sql,String sqlId){
		StringReader reader = null;
		StringWriter out = null;
		Template template = null;
		/** 表达式注入模板 */
		try {
			if(templateCache.get(sqlId)!=null){
				template=templateCache.get(sqlId);
			}
			if(template ==null){
				reader = new StringReader(sql);
				template=createTemplate(DEFAULT_TEMPLATE_KEY, reader);
				templateCache.put(sqlId, template);
			}
			out=new StringWriter();
			template.process(root, out);
			return out.toString();
		} catch (Exception e) {
			throw new DalException("error.dal.005", e );
		}finally {
			if(reader!=null){
				reader.close();
			}
			try {
				if(out!=null){
					out.close();
				}
			} catch (Exception e2) {
				// TODO: handle exception
			}
		}	
	}
	public static void main(String[] args) {
		Map<String,Object> param=new HashMap<String,Object>();
//		param.put("accountNo", "12345");
		String sql="select name from user where 1=1 <#if accountNo?exists && accountNo !=\"\"> AND ACCOUNT_NO=:accountNo </#if>";
		String sqlId="user.queryUserByAccountNo";
		String result=FreeMakerParser.process(param, sql, sqlId);
		System.out.println(result);
	}
}
